package InstanceZone

import (
	codecs "sanguo/codec/cs"
	com_attr "sanguo/node/common/attr"
	"sanguo/node/common/com_type"
	"sanguo/node/common/transaction"
	"sanguo/node/node_game"
	"sanguo/node/node_game/module/role"
	"sanguo/node/node_game/user"
	table_BattleGround "sanguo/node/table/excel/table/BattleGround"
	table_BattleLevel "sanguo/node/table/excel/table/BattleLevel"
	table_GamePlay "sanguo/node/table/excel/table/GamePlay"
	cs_message "sanguo/protocol/cs/message"
	"time"

	"github.com/golang/protobuf/proto"
)

type transactionEnterCampaign struct {
	transaction.TransactionBase
	user    *user.User
	req     *codecs.Message
	resp    *cs_message.EnterCampaignToC
	errcode cs_message.EnumType
}

func (this *transactionEnterCampaign) GetModuleName() string {
	return "InstanceZone"
}

func (this *transactionEnterCampaign) GetReplyMsg() proto.Message {
	return &cs_message.EnterCampaignToC{}
}

func (this *transactionEnterCampaign) SetExpiredTime(expired time.Time) {
	this.Expired = expired
}

func (this *transactionEnterCampaign) GetExpiredTime() time.Time {
	return this.Expired
}

func (this *transactionEnterCampaign) Begin() {
	msg := this.req.GetData().(*cs_message.EnterCampaignToS)
	roleModule := this.user.GetModuleByName("role").(*role.RoleModule)
	role := roleModule.CurrentRole()
	if role == nil || !role.IsRoleModleData() {
		node_game.Infoln(this.user.GetUserID(), "EnterCampaign fail : no selectRole ")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}
	node_game.Infof("%s %d Call EnterCampaign index:%d id:%d power:%d", role.GetUserID(), role.GetID(), msg.GetIndex(), msg.GetBattleGroundID(), msg.GetExplorePower())

	//验证功能开启
	if role.GetLev() < table_GamePlay.Table_.IDMap[com_type.GamePaly_YhBattleGround].UnlockLevel {
		node_game.Infoln(role.GetUserID(), role.GetID(), "fail YhbattleGround System is not Unlock")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	if role.GetWeapon1() == 0 && role.GetWeapon2() == 0 {
		node_game.Infoln(role.GetUserID(), role.GetID(), "EnterInstanceZone fail:no weapon")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	BGDef := table_BattleGround.Table_.IDMap[msg.GetBattleGroundID()]
	if BGDef == nil {
		node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail : BGDef is nil")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	if msg.GetIndex() <= 0 || msg.GetIndex() > BGDef.Count {
		node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail : msg.GetIndex() is fail")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	//判断倍率是否正确
	funcPower := func(power int32) bool {
		if role.GetLev() < BGDef.ExploreUnlockLevel && power != 1 {
			return false
		}

		if power == int32(1) || power == int32(2) || power == int32(3) || power == int32(5) {
			return true
		} else {
			return false
		}
	}

	if !funcPower(msg.GetExplorePower()) {
		node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail : ExplorePower is fail")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	//判断当前角色是否在进行副本
	if role.GetInstanceZone() != nil {
		if role.GetInstanceZone().InitType == com_type.InstanceZone_YhBattleGround {
			battleGround := role.GetBattleGround()
			if battleGround == nil {
				this.errcode = cs_message.EnumType_ERROR
				this.user.EndTrans(this)
				return
			}
			//战役失败,战役结束
			//			if battleGround.Isfailed || battleGround.IsFinally() {
			//				node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign :instanceZone is not nil")
			//				this.errcode = cs_message.EnumType_ERROR
			//				this.user.EndTrans(this)
			//				return
			//			}
			role.ClearInstanceZone()
		} else {
			node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail :instanceZone is not YhBattleGround")
			this.errcode = cs_message.EnumType_ERROR
			this.user.EndTrans(this)
			return
		}
	}

	Diamond, _ := role.GetRoleAttr().GetAttr(com_attr.Diamond)
	gold, _ := role.GetRoleAttr().GetAttr(com_attr.Gold)
	YHBattleGroundEnterTimes, _ := role.GetRoleAttr().GetAttr(com_attr.YHBattleGroundEnterTimes)

	//判断是否初始化战场
	if role.GetBattleGround() != nil {
		battleGround := role.GetBattleGround()
		if battleGround.BattleGroundID != msg.GetBattleGroundID() {
			node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail : BattleGroundID is fail")
			this.errcode = cs_message.EnumType_ERROR
			this.user.EndTrans(this)
			return
		}

		//战役已经结束 在来请求判断为再次挑战战场 清空原战场
		if battleGround.IsFailed || battleGround.IsFinally() {
			role.ClearBattleGround()
		}
	}

	if role.GetBattleGround() == nil {
		if msg.GetExplorePower() != 1 {
			//探索倍率消耗钻石
			Diamond -= int64(msg.GetExplorePower()) * int64(BGDef.DiamondCost)
			if Diamond < 0 {
				node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail : Diamond is fail")
				this.errcode = cs_message.EnumType_ERROR
				this.user.EndTrans(this)
				return
			}
		}
		role.InitBattleGround(msg.GetBattleGroundID(), msg.GetExplorePower())
		if role.GetBattleGround() == nil {
			node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail : InitBattleGround is fail")
			this.errcode = cs_message.EnumType_ERROR
			this.user.EndTrans(this)
			return
		}

	}

	battleGround := role.GetBattleGround()
	battleLevel := battleGround.GetBattleLevelByIndex(msg.GetIndex())

	if battleLevel == nil {
		node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail:battleLevel is nil")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	BattleLevelDef := table_BattleLevel.Table_.IDMap[battleLevel.BattleLevelID]
	if BattleLevelDef == nil || BattleLevelDef.Type != com_type.InstanceZone_YhBattleGround {
		node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail:BattleLevelDef is nil")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	YHBattleGroundEnterTimes -= int64(battleGround.ExplorePower)
	if YHBattleGroundEnterTimes < 0 {
		//免费次数已用尽 消耗金币
		gold -= int64(BattleLevelDef.GoldCost) * (-YHBattleGroundEnterTimes)
		YHBattleGroundEnterTimes = 0
		if gold < 0 {
			node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail : Gold is not enough")
			this.errcode = cs_message.EnumType_ERROR
			this.user.EndTrans(this)
			return
		}
	}

	if !battleGround.EnterCampaign(msg.GetIndex()) {
		//
		node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign fail : EnterCampaign is fail")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	//扣除
	role.GetRoleAttr().SetAttr(com_attr.YHBattleGroundEnterTimes, YHBattleGroundEnterTimes)
	role.GetRoleAttr().SetAttr(com_attr.Diamond, Diamond)
	role.GetRoleAttr().SetAttr(com_attr.Gold, gold)

	this.resp = &cs_message.EnterCampaignToC{
		BattleLevelID: proto.Int32(battleLevel.BattleLevelID),
		BuffID:        proto.Int32(battleLevel.BuffID),
		Degree:        proto.Int32(battleLevel.Degree),
	}

	node_game.Infoln(role.GetUserID(), role.GetID(), "EnterCampaign OK")
	this.errcode = cs_message.EnumType_OK
	this.user.EndTrans(this)
}

func (this *transactionEnterCampaign) End() {
	if this.errcode == cs_message.EnumType_OK {
		this.resp.Errcode = cs_message.EnumType(this.errcode).Enum()
	} else {
		this.resp = &cs_message.EnterCampaignToC{
			Errcode: cs_message.EnumType(this.errcode).Enum(),
		}
	}
	this.user.Reply(this.req.GetSeriNo(), this.resp)
}

func (this *transactionEnterCampaign) Timeout() {
	this.errcode = cs_message.EnumType_RETRY
	this.user.EndTrans(this)
}

func init() {
	user.RegisterTransFunc(&cs_message.EnterCampaignToS{}, func(user *user.User, msg *codecs.Message) transaction.Transaction {
		return &transactionEnterCampaign{
			user: user,
			req:  msg,
		}
	})
}
